package io.github.bloquesoft.entity.clazz.value;

import io.github.bloquesoft.entity.clazz.ClassEntityDefinition;
import io.github.bloquesoft.entity.clazz.ClassListPropertyDefinition;
import io.github.bloquesoft.entity.clazz.ClassPojoPropertyDefinition;
import io.github.bloquesoft.entity.definition.EntityDefinition;
import io.github.bloquesoft.entity.definition.PojoPropertyDefinition;
import io.github.bloquesoft.entity.value.AbstractValue;
import io.github.bloquesoft.entity.value.EntityValue;
import io.github.bloquesoft.entity.value.ListPropertyValue;
import io.github.bloquesoft.entity.value.PojoPropertyValue;
import lombok.Getter;

import java.util.ArrayList;
import java.util.List;

public class ObjectEntityValue extends AbstractValue implements EntityValue {

    private final ObjectEntityValue parentEntityValue;

    @Getter
    private final ClassEntityDefinition classEntityDefinition;

    private List<PojoPropertyValue> pojoPropertyValueList = null;

    private List<ListPropertyValue> listPropertyValueList = null;

    private PojoPropertyValue primaryKeyValue;

    public ObjectEntityValue(ClassEntityDefinition entityDefinition, Object entityObject, ObjectEntityValue parent) {
        super(entityObject);
        this.classEntityDefinition = entityDefinition;
        this.parentEntityValue = parent;
    }

    @Override
    public EntityDefinition getEntityDefinition() {
        return this.classEntityDefinition;
    }

    @Override
    public PojoPropertyValue getPrimaryKeyValue() {
        if (this.primaryKeyValue == null) {
            if (!super.isNullValue()) {
                ClassPojoPropertyDefinition pkProperty = this.getClassEntityDefinition().getClassPrimaryKeyProperty();
                if (pkProperty != null) {
                    this.primaryKeyValue = this.getPojoPropertyValueList().stream().filter(i -> i.getPropertyId().equals(pkProperty.getId())).findFirst().orElse(null);
                }
            }
        }
        return this.primaryKeyValue;
    }

    @Override
    public PojoPropertyValue getPojoPropertyValue(String propertyId) {
        return this.getPojoPropertyValueList().stream().filter(i -> i.getPropertyId().equals(propertyId)).findFirst().orElse(null);
    }

    @Override
    public ListPropertyValue getListPropertyValue(String propertyId) {
        return this.getListPropertyValueList().stream().filter(i -> i.getPropertyId().equals(propertyId)).findFirst().orElse(null);
    }

    @Override
    public List<PojoPropertyValue> getPojoPropertyValueList() {
        if (this.pojoPropertyValueList == null) {
            this.pojoPropertyValueList = new ArrayList<>();
            if (!super.isNullValue()) {
                for (ClassPojoPropertyDefinition pojoProperty : this.getClassEntityDefinition().getClassPojoPropertyList()) {
                    ObjectPojoPropertyValue pojoPropertyValue = new ObjectPojoPropertyValue(pojoProperty, this);
                    this.pojoPropertyValueList.add(pojoPropertyValue);
                }
            }
        }
        return this.pojoPropertyValueList;
    }

    @Override
    public List<ListPropertyValue> getListPropertyValueList() {
        if (this.listPropertyValueList == null) {
            this.listPropertyValueList = new ArrayList<>();
            if (!super.isNullValue()) {
                for (ClassListPropertyDefinition listProperty : this.getClassEntityDefinition().getClassListPropertyList()) {
                    ObjectListPropertyValue listPropertyValue = new ObjectListPropertyValue(listProperty, this);
                    this.listPropertyValueList.add(listPropertyValue);
                }
            }
        }
        return this.listPropertyValueList;
    }

    /**
     * 处理实体内的具有ParentId注解的属性，为其赋值，从父级实体获取Id值并赋值。
     */
    @Override
    public void handleParentIdPojoProperty()
    {
        if(this.parentEntityValue != null)
        {
            //this.parentEntityValue 不为空说明本实体必然有父级实体，否则前面构造的时候必须是有值的。
            Object parentIdValue = this.parentEntityValue.getPrimaryKeyValue().getValue();
            if (parentIdValue == null) {
                throw new RuntimeException("Parent id value is null, could not set null value for parentid, pojo property");
            }
            PojoPropertyDefinition parentPojoProperty = this.getClassEntityDefinition().getParentPojoProperty();
            if (parentPojoProperty != null) {
                PojoPropertyValue pojoPropertyValue = this.getPojoPropertyValue(parentPojoProperty.getId());
                pojoPropertyValue.setValue(parentIdValue);
            }
        }
    }
}